package main

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/qiniu/api.v7/auth/qbox"
	"github.com/qiniu/api.v7/storage"
	"github.com/syyongx/php2go"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sync"
)

var Isok  =false

var accessKey="z8NmWKeLfzU8ev6V95xojZu5GmxgNKibNuaWc0Ef"
var secretKey="SMqml0QjGtU2LHbBKhnSP1JX9Ej_oW0yBzuOEBYh"
var bucket="anqi"
func  QiNiuUpload(path string,fileName string) string {

	//accessKey := "z8NmWKeLfzU8ev6V95xojZu5GmxgNKibNuaWc0Ef"
	//secretKey :=  "SMqml0QjGtU2LHbBKhnSP1JX9Ej_oW0yBzuOEBYh"
	localFile := path
	//bucket := "anqi"
	key :=  "GO_wlphp.cn_tou_"+fileName
	putPolicy := storage.PutPolicy{
		Scope: bucket,
	}
	mac := qbox.NewMac(accessKey, secretKey)
	upToken := putPolicy.UploadToken(mac)

	cfg := storage.Config{}
	cfg.Zone = &storage.ZoneHuadong
	cfg.UseHTTPS = false
	cfg.UseCdnDomains = false

	formUploader := storage.NewFormUploader(&cfg)
	ret := storage.PutRet{}

	putExtra := storage.PutExtra{
		Params: map[string]string{
			"x:name": "github logo",
		},
	}
	err := formUploader.PutFile(context.Background(), &ret, upToken, key, localFile, &putExtra)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	fmt.Println(ret.Key, ret.Hash)
	Isok=true
	return ret.Key

}

func Qie(path string,fileName string)  {
	putPolicy := storage.PutPolicy{
		Scope: bucket,
	}
	localFile := path
	//bucket := "anqi"
	key :=  "GO_wlphp.cn_tou_"+fileName


	mac := qbox.NewMac(accessKey, secretKey)
	upToken := putPolicy.UploadToken(mac)
	cfg := storage.Config{}
	// 空间对应的机房
	cfg.Zone = &storage.ZoneHuadong
	// 是否使用https域名
	cfg.UseHTTPS = false
	// 上传是否使用CDN上传加速
	cfg.UseCdnDomains = false
	resumeUploader := storage.NewResumeUploader(&cfg)
	ret := storage.PutRet{}
	putExtra := storage.RputExtra{
	}
	err := resumeUploader.PutFile(context.Background(), &ret, upToken, key, localFile, &putExtra)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(ret.Key, ret.Hash)
}

func md5Hex(str string) string {
	h := md5.New()
	h.Write([]byte(str))
	return hex.EncodeToString(h.Sum(nil))
}
type ProgressRecord struct {
	Progresses []storage.BlkputRet `json:"progresses"`
}
func Duan(path string,fileName string) {
	localFile :=path
	bucket :=bucket
	key :=  "GO_wlphp.cn_tou_"+fileName
	putPolicy := storage.PutPolicy{
		Scope: bucket,
	}
	mac := qbox.NewMac(accessKey, secretKey)
	upToken := putPolicy.UploadToken(mac)
	cfg := storage.Config{}
	// 空间对应的机房
	cfg.Zone = &storage.ZoneHuadong
	// 是否使用https域名
	cfg.UseHTTPS = false
	// 上传是否使用CDN上传加速
	cfg.UseCdnDomains = false
	// 必须仔细选择一个能标志上传唯一性的 recordKey 用来记录上传进度
	// 我们这里采用 md5(bucket+key+local_path+local_file_last_modified)+".progress" 作为记录上传进度的文件名
	fileInfo, statErr := os.Stat(localFile)
	if statErr != nil {
		fmt.Println(statErr)
		return
	}
	fileSize := fileInfo.Size()
	fileLmd := fileInfo.ModTime().UnixNano()
	recordKey := md5Hex(fmt.Sprintf("%s:%s:%s:%s", bucket, key, localFile, fileLmd)) + ".progress"
	// 指定的进度文件保存目录，实际情况下，请确保该目录存在，而且只用于记录进度文件
	recordDir := "D:\\progress"
	mErr := os.MkdirAll(recordDir, 0755)
	if mErr != nil {
		fmt.Println("mkdir for record dir error,", mErr)
		return
	}
	recordPath := filepath.Join(recordDir, recordKey)


	fmt.Println("进度",recordKey)
	progressRecord := ProgressRecord{}
	// 尝试从旧的进度文件中读取进度
	recordFp, openErr := os.Open(recordPath)
	if openErr == nil {
		progressBytes, readErr := ioutil.ReadAll(recordFp)
		if readErr == nil {
			mErr := json.Unmarshal(progressBytes, &progressRecord)
			if mErr == nil {
				// 检查context 是否过期，避免701错误
				for _, item := range progressRecord.Progresses {
					if storage.IsContextExpired(item) {
						fmt.Println(item.ExpiredAt)
						progressRecord.Progresses = make([]storage.BlkputRet, storage.BlockCount(fileSize))
						break
					}
				}
			}
		}
		recordFp.Close()
	}
	if len(progressRecord.Progresses) == 0 {
		progressRecord.Progresses = make([]storage.BlkputRet, storage.BlockCount(fileSize))
	}
	resumeUploader := storage.NewResumeUploader(&cfg)
	ret := storage.PutRet{}
	progressLock := sync.RWMutex{}
	putExtra := storage.RputExtra{
		Progresses: progressRecord.Progresses,
		Notify: func(blkIdx int, blkSize int, ret *storage.BlkputRet) {
			progressLock.Lock()
			progressLock.Unlock()
			//将进度序列化，然后写入文件
			progressRecord.Progresses[blkIdx] = *ret
			progressBytes, _ := json.Marshal(progressRecord)
			fmt.Println("write progress file", blkIdx, recordPath)
			wErr := ioutil.WriteFile(recordPath, progressBytes, 0644)
			if wErr != nil {
				fmt.Println("write progress file error,", wErr)
			}
		},
	}
	err := resumeUploader.PutFile(context.Background(), &ret, upToken, key, localFile, &putExtra)
	if err != nil {
		fmt.Println(err)
		return
	}
	//上传成功之后，一定记得删除这个进度文件
	//os.Remove(recordPath)
	fmt.Println(ret.Key, ret.Hash)
}
func main()  {



	if len(os.Args) > 1 {
		filepath:=os.Args[1]
		fmt.Println("正在跑代码上传"+filepath)

		filenameWithSuffix := path.Base(filepath) //获取文件名带后缀

		fmt.Println("文件名"+filenameWithSuffix)

		var fileSuffix string
		fileSuffix = path.Ext(filenameWithSuffix) //获取文件后缀
		fmt.Println("fileSuffix =", fileSuffix)

		Qie(filepath,php2go.Uniqid("")+fileSuffix)
	}else{
		fmt.Println("没有命令行参数")
	}

	for{
		if Isok==true {
			break
		}else{

		}
	}


}